/*   Valhalla MailChecker -- Simple IMAP Mail Checker
*    Copyright (C) 2010-2011  Guillaume Florimond (gflorimond at gmail dot com)
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package fr.valhalla.mailcheck;

import fr.valhalla.mailcheck.gui.classic.CheckMessagesFrame;
import fr.valhalla.mailcheck.gui.classic.CheckPane;
import fr.valhalla.mailcheck.gui.Notification;
import fr.valhalla.mailcheck.utils.DateTime;
import fr.valhalla.mailcheck.utils.SoundPlayer;
import java.awt.Component;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 *
 * @author guillaume
 */
public class Checker extends Thread {

    public int AllMessages = 0;
    public int NewMessages = 0;
    public int OldMessages = 0;
    public int ReadMessages = 0;
    public int UnreadMessages = 0;

    public String lastUpdate;
    public String nextUpdate;
    public int sleep;

    private CheckMessagesFrame checkFrame;
    private CheckPane checkPanel;
    private Account account;
    private IMAPConnection imap;
    private Kernel kernel;

    private boolean running; // pour arrêter le thread depuis que stop() est deprecated, cf. documentation Java

    public Checker(Account account, Kernel kernel) {
        this.kernel = kernel;
        checkPanel = new CheckPane(this);
        checkFrame = new CheckMessagesFrame(checkPanel);
        this.account = account;
        sleep = account.getSleep();
        super.setName(account  +"-checker");
    }

    public Checker(Account account, Kernel kernel, CheckPane checkPanel) {
        this.kernel = kernel;
        this.checkPanel = checkPanel;
        checkFrame = new CheckMessagesFrame(checkPanel);
        this.account = account;
        sleep = account.getSleep();
        super.setName(account  +"-checker");
    }

    public JPanel getCheckPanel() {
        return checkPanel;
    }

    public JFrame getCheckFrame() {
        return checkFrame;
    }

    public Account getAccount() {
        return account;
    }

    public void showCheckFrame() {
        checkFrame.setVisible(true);
    }

    public void hideCheckFrame() {
        checkFrame.setVisible(false);
    }

    @Override
    @SuppressWarnings({"static-access", "static-access"})
    public void run() {
        running = true;
        System.out.println("Checker " + account.getAccountName() + " started");
        // Connect to server
        imap = new IMAPConnection();
        boolean co = imap.openConnection(account.getLogin(), account.getPassword(), account.getProtocol(), account.getHost(), account.getPort(), account.isSSL());
        // Open given FOLDER
        String folder = "";
        try {
            if(account.getFolder().isEmpty())
                folder = "Inbox";
            else
                folder = account.getFolder();
        } catch (Exception e) {
            folder = "Inbox";
        }
        // LOOP
        while(running && !interrupted()) {
            System.out.println("[" + account.getAccountName() + "] Opening mailbox {" + folder + "}.");
            if(co == true) {
                imap.openMailBox(folder);
                System.out.println("[" + account.getAccountName() + "] Mailbox opened.");
            }
            else System.out.println("Connexion failure. Trying again in " + (sleep * 1000) + " seconds...");

            lastUpdate = DateTime.now("HH:mm:ss");
            nextUpdate = DateTime.inXSeconds(sleep, "HH:mm:ss");

            int difference = imap.countAllMessages() - AllMessages; // variable globale garde sa valeur de la dernière loop

            AllMessages = imap.countAllMessages();
            NewMessages = imap.countNewMessages();
            OldMessages = imap.countOldMessages();
            ReadMessages = imap.countReadMessages();
            UnreadMessages = imap.countUnreadMessages();

            updateGUI(); // self-explanatory...

            // new mail !
            if(difference > 0) {
                System.out.println("\n=== YOU HAVE NEW MAIL ! ["+ account.getAccountName() + "] ===");
                // update list
                updateList(difference, imap.countAllMessages());
                // Play new mail sound
                if(account.getSound() == null ? "NONE" != null : !account.getSound().equals("NONE"))
                    try {
                        SoundPlayer sound = new SoundPlayer(account.getSound());
                        sound.play();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                // Show notification !
                if(account.hasNotifications() && kernel.withGUI()) {
                    int msgid = imap.countAllMessages() - 1; // arrays begin at 0
                    String from = imap.getFromAddress(msgid);
                    String subject = imap.getMessageSubject(msgid);
                    String datetime = imap.getMessageDate(msgid);
                    new Thread(new Notification(account.getAccountName(), from, datetime, subject)).start();
                }
            }

            System.out.println(   "\n----------["+ account.getAccountName() +"]----------\n"
                                + "| " + NewMessages + " nouveaux\n"
                                + "| " + OldMessages + " anciens\n"
                                + "| " + UnreadMessages + " non lus\n"
                                + "| " + ReadMessages + " lus\n"
                                + "| Total : " + AllMessages + " messages\n"
                                + "----------["+ account.getAccountName() +"]----------"
                              );
            System.out.println("\n[" + account.getAccountName() + "] Sleeping.");
            System.out.println("[" + account.getAccountName() + "] Next check : " + nextUpdate + "\n");
            try {
                this.sleep(sleep * 1000);
            } catch(InterruptedException e) {;}
        }
        imap.closeConnection();
        System.out.println("Checker " + account.getAccountName() + " stopped");
    }

    public void stopChecker() {
        running = false;
        interrupt();
    }

    private void updateGUI() {
        checkPanel.setAccountName(account.getAccountName());
        checkPanel.setAllMessagesCount(AllMessages);
        checkPanel.setNewMessagesCount(NewMessages);
        checkPanel.setUnreadMessagesCount(UnreadMessages);
        checkPanel.setLastUpdate(lastUpdate);
        checkPanel.setNextUpdate(nextUpdate);

        checkFrame.setAccountName(account.getAccountName());
        checkFrame.setAllMessagesCount(AllMessages);
        checkFrame.setNewMessagesCount(NewMessages);
        checkFrame.setLastUpdate(lastUpdate);
        checkFrame.setNextUpdate(nextUpdate);
    }

    private void updateList(int x, int y) {
        for(int i = x ; i > 0 ; i--) {
            int id = y - i;
            String display = "[" + imap.getMessageDate(id) + "] "
                           + "[" + imap.getFromAddress(id) + "] "
                           + imap.getMessageSubject(id);
            if(imap.isNew(id))
                display = "[N]" + display;
            if(!imap.isRead(id))
                display = "[*]" + display;
            
            checkFrame.addToList(display);

            // Update progress bar
            checkFrame.setProgress(id, y);
        }

        // Remove progress bar
        checkFrame.removeProgressBar();

    }

    public Kernel getKernel() {
        return kernel;
    }

    public IMAPConnection getConnection() {
        return imap;
    }

}
